package com.myna.csv.extractor;

import com.myna.csv.domain.RDCEntity;
import com.myna.csv.domain.RDCProperty;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.myna.csv.batch.ProcessBatchQueues.*;
import static com.myna.csv.initial.InitialProcessor.*;

public class PublicExtractor<T> {
    public static final Logger LOGGER = LogManager.getLogger(PublicExtractor.class);

    public static XMLStreamReader xmlStreamReader = null;
    public static GZIPInputStream gis;
    public List<RDCProperty> properties;

    public Boolean isInstrument(XMLStreamReader reader) throws XMLStreamException {
        while (reader.hasNext()) {
            int eventType = reader.next();
            if (XMLStreamConstants.START_ELEMENT == eventType && "entity".equals(reader.getLocalName())) {
                String type = reader.getAttributeValue("", "type");
                if ("I".equals(type)) {
                    return true;
                }
            }
        }
        return false;
    }

    public XMLStreamReader openXmlStreamReader(InputStream inputStream) {

        try {
            gis = new GZIPInputStream(inputStream);
            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
            xmlStreamReader = xmlInputFactory.createXMLStreamReader(new BufferedReader(
                    new InputStreamReader(gis, "UTF-8"), 1024 * 1024));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return xmlStreamReader;
    }

    public void closeStream(XMLStreamReader xmlStreamReader,
                            GZIPInputStream gis, XMLStreamReader xmlStreamReader2, InputStream inputStream) {
        try {
            if (xmlStreamReader != null) {
                xmlStreamReader.close();
            }
            if (gis != null) {
                gis.close();
            }
            if (xmlStreamReader2 != null) {
                xmlStreamReader2.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void readRDCEntity(RDCEntity rdcEntity, XMLStreamReader reader) throws XMLStreamException {
        properties = new ArrayList<>();

        //get Attributes
        String type = reader.getAttributeValue("", "type");
        String subtype = reader.getAttributeValue("", "subtype");
        String rcssubtype = reader.getAttributeValue("", "rcssubtype");

        rdcEntity.setType(type);
        rdcEntity.setSubtype(subtype);
        rdcEntity.setRcs_subtype(rcssubtype);

        String localName;
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamConstants.END_ELEMENT:
                    localName = reader.getLocalName();
                    switch (localName) {
                        case "entity":
                            rdcEntity.setRdcProperties(properties);
                            properties = new ArrayList<>();
                            return;
                    }
                    break;
                case XMLStreamConstants.START_ELEMENT:
                    localName = reader.getLocalName();
                    switch (localName) {
                        case "PI":
                            rdcEntity.setPi(Long.valueOf(reader.getElementText()));
                            break;
                        case "content":
                            RDCProperty property = new RDCProperty();
                            readRDCProperty(reader, property, type);
                            break;
                    }
                    break;
            }
        }
    }

    //Extractor RDCProperty
    public void readRDCProperty(XMLStreamReader reader, RDCProperty property, String type) throws XMLStreamException {
        while (reader.hasNext()) {
            int eventType = reader.next();
            String localName;
            switch (eventType) {
                case XMLStreamConstants.END_ELEMENT:
                    localName = reader.getLocalName();
                    if ("content".equals(localName)) {
                        return;
                    }
                    break;
                case XMLStreamConstants.START_ELEMENT:
                    localName = reader.getLocalName();
                    if ("property".equals(localName)) {
                        property = new RDCProperty();
                        String propertyId = reader.getAttributeValue(null, "id");
                        property.setProperty_id(Long.valueOf(propertyId));
                        property.setProperty_name(jsonMappingMap.get(Long.valueOf(propertyId)));
                        readRDCPropertyName(reader, property);

                        if ("I".equals(type)) {
                            if (needed_pi_properIds_List.contains(propertyId)) {
                                properties.add(property);
                            }
                        } else if ("Q".equals(type) || "O".equals(type)) {
                            if (StubProper_properIds_List.contains(propertyId)) {
                                properties.add(property);
                            }
                        }
                    }
                    break;
            }
        }
    }

    public void readRDCPropertyName(XMLStreamReader reader, RDCProperty property) throws XMLStreamException {
        String localName;
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamConstants.END_ELEMENT:
                    localName = reader.getLocalName();
                    switch (localName) {
                        case "property":
                            return;
                    }
                    break;
                case XMLStreamConstants.START_ELEMENT:
                    localName = reader.getLocalName();
                    switch (localName) {
                        case "currValue":
                            property.setCurrValue(reader.getElementText().intern());
                            break;
                        case "validFrom":
                            property.setValidFrom(reader.getElementText().intern());
                            break;
                        case "validFromWithTime":
                            property.setValidFromWithTime(reader.getElementText().intern());
                            break;
                        case "validTo":
                            property.setValidTo(reader.getElementText().intern());
                            break;
                        case "validToWithTime":
                            property.setValid_to_inc_time(reader.getElementText().intern());
                            break;
                    }
                    break;
            }
        }
    }

    public File setFileTitle(String rdcFilePath, String fileName) {
        File file = null;
        file = new File(rdcFilePath + fileName);
        BufferedWriter out = null;
        try {
            if (file.exists()) {
                file.delete();
            } else {
                file.createNewFile();
            }

            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8"));
            String title = "\"PI\", \"type\", \"subtype\", \"rcsSubType\", \"propertyId\"," +
                    "\"propertyName\", \"currValue\", \"validFrom\",\"validFromWithTime\"," +
                    " \"validTo\", \"validToWithTime\"";
            out.write(title);
            out.newLine();
            out.flush();

        } catch (Exception e) {
            LOGGER.info("setFileTitle error", e);
        } finally {
            if (!Objects.isNull(out)) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    public void writeToCSVFile(Long pi, RDCEntity rdcEntity, String flag) {
        try {
            List<RDCProperty> rdcProperties = null;
            StringBuffer buffer = null;

            if (!Objects.isNull(rdcEntity)) {
                rdcProperties = rdcEntity.getRdcProperties();
                if (rdcProperties.size() > 0) {
                    for (int i = 0; i < rdcProperties.size(); i++) {
                        RDCProperty rdcProperty = rdcProperties.get(i);
                        buffer = new StringBuffer();
                        buffer.append("\"").append(String.valueOf(pi)).append("\", ").
                                append("\"").append(rdcEntity.getType()).append("\", ").
                                append("\"").append(rdcEntity.getSubtype()).append("\", ").
                                append("\"").append(rdcEntity.getRcs_subtype()).append("\", ").
                                append("\"").append(String.valueOf(rdcProperty.getProperty_id())).append("\", ").
                                append("\"").append(rdcProperty.getProperty_name()).append("\", ").
                                append("\"").append(rdcProperty.getCurrValue()).append("\", ").
                                append("\"").append(rdcProperty.getValidFrom()).append("\", ").
                                append("\"").append(rdcProperty.getValidFromWithTime()).append("\", ").
                                append("\"").append(rdcProperty.getValidTo()).append("\", ").
                                append("\"").append(rdcProperty.getValid_to_inc_time()).append("\"");
                        if ("UNDERLYING".equals(flag)) {
                            underlyingQue.add(buffer.toString());
                        } else if ("BODYGROUP".equals(flag)) {
                            bodyGroupQue.add(buffer.toString());
                        } else if ("ISIN".equals(flag)) {
                            stubISINQue.add(buffer.toString());
                        }
                    }
                } else {
                    buffer = new StringBuffer();
                    buffer.append("\"").append(String.valueOf(pi)).append("\", ").
                            append("\"").append(rdcEntity.getType()).append("\", ").
                            append("\"").append(rdcEntity.getSubtype()).append("\", ").
                            append("\"").append(rdcEntity.getRcs_subtype()).append("\"");
                    if ("UNDERLYING".equals(flag)) {
                        underlyingQue.add(buffer.toString());
                    } else if ("BODYGROUP".equals(flag)) {
                        bodyGroupQue.add(buffer.toString());
                    } else if ("ISIN".equals(flag)) {
                        stubISINQue.add(buffer.toString());
                    }
                }
            } else {
                buffer = new StringBuffer();
                buffer.append("\"").append(String.valueOf(pi)).append("\"");
                if ("UNDERLYINGPI".equals(flag)) {
                    underlyingPIQue.add(buffer.toString());
                } else if ("BODYGROUPPI".equals(flag)) {
                    bodyGroupPIQue.add(buffer.toString());
                }
            }
        } catch (Exception e) {
            LOGGER.info("Write to CSV File error", e);
        }
    }

//    public void writeToCSVFile(Long pi, RDCEntity rdcEntity, File file) {
//        BufferedWriter out = null;
//        try {
//            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8"));
//            List<RDCProperty> rdcProperties = null;
//            if (!Objects.isNull(rdcEntity)) {
//
//                rdcProperties = rdcEntity.getRdcProperties();
//                if (rdcProperties.size() > 0) {
//                    for (int i = 0; i < rdcProperties.size(); i++) {
//                        RDCProperty rdcProperty = rdcProperties.get(i);
//                        out.write("\"" + String.valueOf(pi) + "\", ");
//                        out.write("\"" + rdcEntity.getType() + "\", ");
//                        out.write("\"" + rdcEntity.getSubtype() + "\", ");
//                        out.write("\"" + rdcEntity.getRcs_subtype() + "\", ");
//                        out.write("\"" + String.valueOf(rdcProperty.getProperty_id()) + "\", ");
//                        out.write("\"" + rdcProperty.getProperty_name() + "\", ");
//                        out.write("\"" + rdcProperty.getCurrValue() + "\", ");
//                        out.write("\"" + rdcProperty.getValidFrom() + "\", ");
//                        out.write("\"" + rdcProperty.getValidFromWithTime() + "\", ");
//                        out.write("\"" + rdcProperty.getValidTo() + "\", ");
//                        out.write("\"" + rdcProperty.getValid_to_inc_time() + "\"");
//                        out.newLine();
//                        out.flush();
//                    }
//                } else {
//                    out.write("\"" + String.valueOf(pi) + "\", ");
//                    out.write("\"" + rdcEntity.getType() + "\", ");
//                    out.write("\"" + rdcEntity.getSubtype() + "\", ");
//                    out.write("\"" + rdcEntity.getRcs_subtype() + "\", ");
//                    out.newLine();
//                    out.flush();
//                }
//            } else {
//                out.write("\"" + String.valueOf(pi) + "\", ");
//                out.newLine();
//                out.flush();
//            }
//        } catch (Exception e) {
//            LOGGER.info("Write to CSV File error", e);
//        } finally {
//            if (!Objects.isNull(out)) {
//                try {
//                    out.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//    }

    public void zipFile(File file, String zipFileName) {
        //定义压缩文件的名称
        File zipFile = new File(rdcFilePath + zipFileName);
        //定义输入文件流
        InputStream input = null;
        ZipOutputStream zipOut = null;
        try {
            input = new FileInputStream(file);
            zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            zipOut.putNextEntry(new ZipEntry(file.getName()));
            int temp = 0;
            while ((temp = input.read()) != -1) {
                zipOut.write(temp);
                zipOut.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!Objects.isNull(input)) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (!Objects.isNull(zipOut)) {
                try {
                    zipOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void delFile(File file) {
        if (file.exists()) {
            file.delete();
        }
    }
}
